#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "hi_io.h"
#include "hi_time.h"
#include "lwip/sockets.h"
#include "net_demo.h"
#include <errno.h>

#include <hi_stdlib.h>
#include <hi_uart.h>
#include "app_demo_uart.h"
#include <iot_uart.h>
#include <hi_gpio.h>
// #include <hi_io.h>
#include "iot_gpio_ex.h"
//#include "iot_gpio.h"

// #define TASK_STAK_SIZE    (1024*10)
#define GPIO_12 12 // EC
#define GPIO_11 11 // TR
// #define GPIO_8 8   //EC
// #define GPIO_7 7    //TR
#define GPIO_FUNC 0
//

//
#define LED_TEST_GPIO 9
#define LED_INTERVAL_TIME_US 300000
UartDefConfig uartDefConfig = {0};
//

//
char distence = 0;
char de_flag = 0;
char *dflag = &de_flag;
char *dflag2 = &de_flag;
char *dis = &distence;
char *dis2 = &distence;
static char g_request[128] = "0";
//

static void Uart1GpioCOnfig(void)
{
#ifdef ROBOT_BOARD
    IoSetFunc(HI_IO_NAME_GPIO_5, IOT_IO_FUNC_GPIO_5_UART1_RXD);
    IoSetFunc(HI_IO_NAME_GPIO_6, IOT_IO_FUNC_GPIO_6_UART1_TXD);
    /* IOT_BOARD */
#elif defined(EXPANSION_BOARD)
    IoSetFunc(HI_IO_NAME_GPIO_0, IOT_IO_FUNC_GPIO_0_UART1_TXD);
    IoSetFunc(HI_IO_NAME_GPIO_1, IOT_IO_FUNC_GPIO_1_UART1_RXD);
#endif
}

float GetDistance(void)
{
    static unsigned long start_time = 0, time = 0;
    float distance = 0.0;
    IotGpioValue value = IOT_GPIO_VALUE0;
    unsigned int flag = 0;
    float pi = 0.034;
    int l = 2;
    unsigned int delayTime = 20;
    IoTWatchDogDisable();

    hi_io_set_func(GPIO_12, GPIO_FUNC);
    IoTGpioSetDir(GPIO_12, IOT_GPIO_DIR_IN);

    IoTGpioSetDir(GPIO_11, IOT_GPIO_DIR_OUT);
    IoTGpioSetOutputVal(GPIO_11, IOT_GPIO_VALUE1);
    hi_udelay(delayTime);
    IoTGpioSetOutputVal(GPIO_11, IOT_GPIO_VALUE0);

    while (1)
    {
        IoTGpioGetInputVal(GPIO_12, &value);
        if (value == IOT_GPIO_VALUE1 && flag == 0)
        {
            start_time = hi_get_us();
            flag = 1;
        }
        if (value == IOT_GPIO_VALUE0 && flag == 1)
        {
            time = hi_get_us() - start_time;
            start_time = 0;
            break;
        }
    }
    distance = time * pi / l;
    return distance;
}

// static void robot_hcsr04(void){
//     float distance;
//     unsigned int time = 200;
//     while (1) {
//          distance = GetDistance();
//         *dis = (int)distance;
//         printf("distance is %d\r\n", *dis);
//         osDelay(time);
//     }
// }

static hi_void *UartDemoTask(char *param)
{
    hi_u8 uartBuff[UART_BUFF_SIZE] = {0};
    hi_unref_param(param);
    printf("Initialize uart demo successfully, please enter some datas via DEMO_UART_NUM port...\n");
    Uart1GpioCOnfig();
    int f = 0;
    for (;;)
    {
        uartDefConfig.g_uartLen = IoTUartRead(DEMO_UART_NUM, uartBuff, UART_BUFF_SIZE);
        if ((uartDefConfig.g_uartLen > 0) && (uartBuff[0] == 0xaa) && (uartBuff[1] == 0x55))
        {
            for (int i = 0; i < UART_BUFF_SIZE; i++)
            {
                printf("0x%x", uartBuff[i]);
            }
            *dflag = 1;
             //TaskMsleep(200);
        printf("dflag = %d\r\n",*dflag);
        }
        //else *dflag = 0;
        *dis = (int)GetDistance();
       //printf("distence = %d\r\n",*dis);

        IoTGpioSetOutputVal(LED_TEST_GPIO, 1);
        usleep(LED_INTERVAL_TIME_US);
        IoTGpioSetOutputVal(LED_TEST_GPIO, 0);
        usleep(LED_INTERVAL_TIME_US);
        TaskMsleep(20); /* 20:sleep 20ms */
    }
    return HI_NULL;
}

static void TCPserverDemoTask(void)
{

    int backlog = 1;
    int sockfd = socket(AF_INET, SOCK_STREAM, 0); // TCP socket

    struct sockaddr_in clientAddr = {0};
    socklen_t clientAddrLen = sizeof(clientAddr);
    struct sockaddr_in serverAddr = {0};
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(1234);              // 端口号，从主机字节序转为网络字节序
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); // 允许任意主机接入， 0.0.0.0

    ssize_t retval = bind(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); // 绑定端口
    if (retval < 0)

    {
        printf("bind failed, %ld!\r\n", retval);
        printf("do_cleanup...\r\n");
        lwip_close(sockfd);
    }
    printf("bind to port success!\r\n");

    retval = listen(sockfd, backlog); // 开始监听
    if (retval < 0)
    {
        printf("listen failed!\r\n");
        printf("do_cleanup...\r\n");
        lwip_close(sockfd);
    }
    printf("listen with %d backlog success!\r\n", backlog);

    printf("======waiting for client's request======\n");
    int connfd;
    while (1)
    {
        connfd = accept(sockfd, (struct sockaddr *)&clientAddr, &clientAddrLen);
        if (connfd < 0)
        {
            printf("accept failed, %d, %d\r\n", connfd, errno);
            // printf("do_cleanup...\r\n");
            continue;
            // lwip_close(sockfd);
        }
        // printf("accept success, connfd = %d!\r\n", connfd);
        // printf("client addr info: host = %s, port = %d\r\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));

        // 后续 收、发 都在 表示连接的 socket 上进行；
        retval = recv(connfd, g_request, sizeof(g_request), 0);
        if (retval < 0)
        {
            printf("recv g_request failed, %ld!\r\n", retval);
            sleep(1);
            lwip_close(connfd);
            sleep(1); // for debug
            // lwip_close(sockfd);
        } 
         printf("recv g_request{%s} from client done!\r\n", g_request);
        if (!strncmp("dis", g_request, 3))
        {
            // g_request[4] = (char)GetDistance();
            g_request[4] = *dis2;
            g_request[5] = *dflag2;
            printf("send distence=%d success\n", g_request[4]);
            printf("send flag=%d success\n", g_request[5]);
        }
        // retval = send(connfd, g_request, strlen(g_request), 0);
        retval = send(connfd, g_request, 6, 0);
        if (retval <= 0)
        {
            printf("send response failed, %ld!\r\n", retval);
            sleep(1);
            lwip_close(connfd);
            sleep(1); // for debug
            // lwip_close(sockfd);
        }
        printf("send response{%s} to client done!\r\n", g_request);
        *dflag2 = 0;
        lwip_close(connfd);
    }

    lwip_close(sockfd);
}

static void SerialDemoEntry(void)
{

    osThreadAttr_t attr;
    attr.name = "NetDemoTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240; /* 堆栈大小为10240 */
    attr.priority = osPriorityNormal;

    if (osThreadNew(TCPserverDemoTask, NULL, &attr) == NULL)
    {
        printf("[NetDemoEntry] Falied to create NetDemoTask!\n");
    }

    hi_u32 ret = 0;
    IoTGpioInit(LED_TEST_GPIO);
    IoTGpioSetDir(LED_TEST_GPIO, IOT_GPIO_DIR_OUT);
    IotUartAttribute uartAttr = {
        .baudRate = 115200, /* baudRate: 115200 */
        .dataBits = 8,      /* dataBits: 8bits */
        .stopBits = 1,      /* stop bit */
        .parity = 0,
    };
    /* Initialize uart driver */
    ret = IoTUartInit(DEMO_UART_NUM, &uartAttr);
    if (ret != HI_ERR_SUCCESS)
    {
        printf("Failed to init uart! Err code = %d\n", ret);
        return;
    }
    /* Create a task to handle uart communication */
    // osThreadAttr_t attr = {0};
    attr.name = "uart demo";
    attr.stack_size = 1024*5; 
    attr.priority = osPriorityNormal1;
    if (osThreadNew((osThreadFunc_t)UartDemoTask, NULL, &attr) == NULL)
    {
        printf("Falied to create uart demo task!\n");
    }
}

SYS_RUN(SerialDemoEntry);